#include "api_map.h"
#include "stdio.h"

extern api_auto_init_s _api_start;
extern api_auto_init_s _api_end;

typedef struct api_list
{
    struct api_list *next;
    api_item_t api;
} api_list_s, *api_list_t;
static api_list_t api_list_head = NULL;
static api_list_t api_list_end = NULL;

void api_add(api_item_t api)
{
    api_list_t item = malloc(sizeof(api_list_s));
    item->api = api;
    item->next = NULL;
    if (!api_list_head)
        api_list_head = item;
    if (api_list_end)
        api_list_end->next = item;
    api_list_end = item;
}

void api_remove(api_item_t api)
{
    api_list_t last = NULL;
    for (api_list_t item = api_list_head; item; item = item->next)
    {
        if (item->api == api)
        {
            if (!last)
                api_list_head = item->next;
            else
                last->next = item->next;
            if (api_list_end == item)
                api_list_end = last;
            free(item);
            break;
        }
        last = item;
    }
}

api_item_t api_get(char *name)
{
    if (!name || !api_list_head)
        return NULL;
    for (api_list_t item = api_list_head; item; item = item->next)
    {
        if (strcmp(item->api->name, name) == 0)
            return item->api;
    }
    return NULL;
}

void api_call(char *name, http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    api_item_t api = api_get(name);
    if (api)
    {
        api->fn(server, frame, data);
        return;
    }
    printf("api %s not found\n", name);
}
#define API_LIST_FN_POINTER 0
void api_list(void)
{
    printf("api list:\n");
#if !API_LIST_FN_POINTER
    uint16_t count = 0;
    printf("[");
#endif
    for (api_list_t item = api_list_head; item; item = item->next)
    {
#if API_LIST_FN_POINTER
        printf("%s : %p\n", item->api->name, item->api->fn);
#else
        if (count)
            printf(",");
        if (count % 4 == 0)
            printf("\n");
        printf("%20s", item->api->name);
        count++;
#endif
    }
#if !API_LIST_FN_POINTER
    printf("\n]\n");
#endif
}

void api_auto_init(void)
{
    api_auto_init_t start = &_api_start;
    api_auto_init_t end = &_api_end;
    for (; start < end; start++)
        start->init();
}